Typically blocks of memory (data buffers) are pre-allocated for transferring data between applications. The data can be gathered from, or scattered into, a set of data buffers with the pre-allocated set of data buffers being identified through the use of a Scatter-Gather List (SGL). Each entry in the SGL is capable of storing an Address-Length (A/L) pair that identifies a data buffer. A start address for a data buffer is stored in an address field (A) of the A/L pair and the length of the data buffer is stored in a length field (L) of the (A/L) pair typically by application software or device drivers in an operating system.
Typically, all of the memory resources required for an Input/Output (I/O) transfer are allocated before the I/O transfer starts. An I/O transfer refers to a movement of data between data buffers in system memory and a device. In an environment with limited memory resources, such as embedded systems having programs stored in non-volatile memory such as Read Only Memory (ROM) or flash memory, instead of sending all of the data for the I/O transfer in a large single I/O transfer, the data to be transferred may be split up into a plurality of small I/O transfers with the plurality of I/O transfers being performed in linear order. However, splitting the large I/O transfer into a set of smaller I/O transfers reduces overall performance of the large I/O transfer due to the additional overhead required to set up the smaller I/O transfers.
For I/O transfers between initiators and targets in a storage environment, each target includes a queue for storing pending tasks that include I/O transfers. The initiator monitors ‘queue depth’ information provided by the target to determine if the target can accept a new task. For example, in a system in which each task includes one I/O transfer, a target with a queue depth of 8 is capable of currently processing 8 different I/O transfers. If a large I/O transfer is split into a plurality of smaller I/O transfers, optimal resource utilization is not provided because all of the target's resources for I/O transfers may be used for the single large I/O transfer having the many smaller I/O transfers instead of different I/O transfers.
To increase resource utilization, instead of splitting a large I/O transfer into a plurality of smaller I/O transfers, I/O processing for the large I/O transfer is stalled until a resource is released. When the released resource is allocated to the I/O transfer, the I/O transfer is resumed. Although this method does not have the additional overhead to set up many-small-I/O transfers, however, performance is reduced because stalling I/O transfers requires additional Central Processing Unit (CPU) processing cycles.
Also, when an I/O transfer is stalled, the progress of other I/O transfers may be blocked. For example, the blocked I/O transfers may have a resource/buffer available for use by another I/O but because they are blocked they are unable to release the resource/buffer. Blocked I/O transfers typically occur in applications involving serial storage protocols because of the flow control nature of serial storage protocols.
Although the following Detailed Description will proceed with reference being made to illustrative embodiments of the claimed subject matter, many alternatives, modifications, and variations thereof will be apparent to those skilled in the art. Accordingly, it is intended that the claimed subject matter be viewed broadly, and be defined only as set forth in the accompanying claims.